package com.sdweizan.sdk.bytedance.util;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.sdweizan.sdk.bytedance.error.BdErrorException;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.StatusLine;
import org.apache.http.client.HttpResponseException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

@Slf4j
public abstract class HttpClientRequestExecutor<T>
    extends SimpleRequestExecutor<T, Map<String, Object>> {
  protected final CloseableHttpClient httpClient;
  protected final TypeReference<T> typeReference;

  public HttpClientRequestExecutor(TypeReference<T> typeReference) {
    this.typeReference = typeReference;
    this.httpClient =
        HttpClients.custom()
            .setDefaultRequestConfig(
                RequestConfig.custom()
                    .setConnectTimeout(1000)
                    .setConnectionRequestTimeout(1000)
                    .setSocketTimeout(3000)
                    .build())
            .build();
  }

  protected abstract HttpRequestBase buildRequest(
      String requestUri, Map<String, Object> requestBody);

  @Override
  public T execute(String requestUri, Map<String, Object> requestBody)
      throws BdErrorException, IOException {
    return execute(requestUri, requestBody, new HashMap<>());
  }

  @Override
  public T execute(String requestUri, Map<String, Object> requestBody, Map<String, String> header)
      throws BdErrorException, IOException {
    HttpRequestBase httpRequest = buildRequest(requestUri, requestBody);
    httpRequest.addHeader("Content-Type", "application/json;charset=UTF-8");
    header.forEach(httpRequest::addHeader);
    try (CloseableHttpResponse response = httpClient.execute(httpRequest)) {
      final StatusLine statusLine = response.getStatusLine();
      final HttpEntity entity = response.getEntity();
      if (statusLine.getStatusCode() >= 300) {
        EntityUtils.consume(entity);
        throw new HttpResponseException(statusLine.getStatusCode(), statusLine.toString());
      }
      String responseBody =
          handleResponse(entity == null ? null : EntityUtils.toString(entity, Consts.UTF_8));
      log.info("字节服务接口响应：{}", responseBody);
      return Objects.isNull(typeReference)
          ? null
          : JSONObject.parseObject(responseBody, typeReference);
    } finally {
      httpRequest.releaseConnection();
    }
  }
}
